package se.webbzon.boltzmann.minigame;

import java.io.IOException;
import java.net.URL;
import java.util.List;

import se.webbzon.boltzmann.Main;
import se.webbzon.boltzmann.debug.Debug;
import se.webbzon.boltzmann.input.Input;
import se.webbzon.boltzmann.minigame.menu.DefaultMenuLayout;
import se.webbzon.boltzmann.minigame.menu.Menu;
import se.webbzon.boltzmann.minigame.menu.MenuEvent;
import se.webbzon.boltzmann.minigame.menu.MenuLayout;
import se.webbzon.boltzmann.minigame.menu.MenuListener;
import se.webbzon.boltzmann.minigame.page.DefaultPageLayout;
import se.webbzon.boltzmann.minigame.page.DefaultPage;
import se.webbzon.boltzmann.minigame.page.PageItem;
import se.webbzon.boltzmann.minigame.page.PageLayout;
import se.webbzon.boltzmann.minigame.page.PageParser;
import se.webbzon.boltzmann.minigame.question.QuestionController;
import se.webbzon.boltzmann.minigame.sandbox.DefaultSandBox;
import se.webbzon.boltzmann.sound.SoundUtils;
import se.webbzon.boltzmann.sound.Sounds;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.WorldView;

public abstract class Puzzle extends Minigame {
	
	// The URL to the puzzle info and question
	private final URL homeUrl, infoUrl, questionUrl;
	
	// A menu listener
	private final MenuListener listener;
	
	// The puzzle menu
	private Menu menu;
	
	// The puzzle info
	private DefaultPage home, info;
	
	// The question controller
	private QuestionController question;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public Puzzle(String puzzlePath) {
		String path = puzzlePath.endsWith("/") ? puzzlePath : puzzlePath + "/";
		homeUrl = Main.class.getClassLoader().getResource(path + "index.htm");
		infoUrl = Main.class.getClassLoader().getResource(path + "info.htm");
		questionUrl = Main.class.getClassLoader().getResource(path + "resources.xml");
		listener = new MenuListenerImpl();
	}
	
	/*============================================================
	Protected Methods
	============================================================*/
	
	/** Loads the world area of the puzzle. If the world could not be loaded
	 * then null is returned. **/
	protected abstract WorldArea loadPuzzle(WorldView view, Input input);
	
	/** Loads the sand box of the puzzle. **/
	protected abstract void loadSandBox(DefaultSandBox box);
	
	@Override protected final WorldArea load(WorldView view, Input input) {
		PageLayout pLayout = new DefaultPageLayout();
		MenuLayout mLayout = new DefaultMenuLayout();
		
		menu = new Menu(mLayout,input);
		menu.addListener(listener);
		
		home = new DefaultPage(pLayout,input);
		info = new DefaultPage(pLayout,input);
		PageParser parser = new PageParser();
		List<PageItem> items;
		try {
			items = parser.parse(pLayout, homeUrl);
			for (PageItem item : items)
				home.addItem(item);
			items = parser.parse(pLayout, infoUrl);
			for (PageItem item : items)
				info.addItem(item);
		} catch (IOException e) {
			Debug.report(e);
		}
		
		question = new QuestionController(pLayout,input,questionUrl);
		
		WorldArea world = loadPuzzle(view,input); 
		loadSandBox(new DefaultSandBox(world));
		world.createInstance(menu);
		world.createInstance(home);
		world.createInstance(info);
		info.setVisible(false);
		return world;
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** An implementation of a menu listener. **/
	private final class MenuListenerImpl implements MenuListener {

		@Override public void onSelect(MenuEvent event) {
			int newIndex = event.getNewIndex();
			home.setVisible(newIndex == 0);
			info.setVisible(newIndex == 1);
			if (newIndex == 2) {
				SoundUtils.playSingletonSound(Sounds.minigame_01, false);
			}
			if (newIndex == 3) {
				menu.getWorld().createInstance(question);
			} else
				menu.getWorld().destroyInstance(question);
			if (newIndex == 4)
				end();
		}
		
	}

}
